﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.DirectoryServices;
using Microsoft.Web.Administration;
using System.Management;

namespace DevelopAssistant.Common
{
    /// <summary>
    /// IIS 助手
    /// </summary>
    public class IIS7Assistant
    {
        public static string Version
        {
            get
            {
                return GetVersion();
            }
        }

        public static string GetVersion()
        {
            string Version = "未知版本";
            try
            {
                DirectoryEntry getEntity = new DirectoryEntry("IIS://localhost/W3SVC/INFO");
                Version = Convert.ToDecimal(getEntity.Properties["MajorIISVersionNumber"].Value.ToString()).ToString("F2");
            }
            catch (Exception ex)
            {
                Version = ex.Message;
            }
            return Version;
        }

        public static string[] GetAppPools()
        {
            List<string> list = new List<string>();
            try
            {
                //DirectoryEntry appPools = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
                //foreach (DirectoryEntry getdir in appPools.Children)
                //{
                //    list.Add(getdir.Name);
                //}

                using (ServerManager mgr = new ServerManager())
                {
                    foreach (var pool in mgr.ApplicationPools)
                    {
                        list.Add(pool.Name);
                    }
                }

            }
            catch (Exception ex)
            {

            }
            return list.ToArray();
        }

        public static bool IsAppPool(string name)
        {
            using (ServerManager mgr = new ServerManager())
            {
                foreach (var pool in mgr.ApplicationPools)
                {
                    if (pool.Name == name)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public static bool AddAppPool(string name, ProcessModelIdentityType identityType, ManagedPipelineMode appPoolPipelineMode)
        {
            if (IsAppPool(name))
                return false;

            string username = string.Empty;
            string password = string.Empty;
            using (ServerManager mgr = new ServerManager())
            {
                ApplicationPool pool = mgr.ApplicationPools.Add(name);
                if (!String.IsNullOrEmpty(username))
                {
                    pool.ProcessModel.UserName = username;
                    pool.ProcessModel.Password = password;
                }
                if (pool.ProcessModel.IdentityType != identityType)
                {
                    pool.ProcessModel.IdentityType = identityType;
                }
                if (appPoolPipelineMode != pool.ManagedPipelineMode)
                {
                    pool.ManagedPipelineMode = appPoolPipelineMode;
                }
                mgr.CommitChanges();
            }

            return true;
        }

        public static ApplicationPool AddAppPool(string name, ProcessModelIdentityType identityType, ManagedPipelineMode appPoolPipelineMode, out bool success)
        {
            success = false;
            string username = string.Empty;
            string password = string.Empty;
            using (ServerManager mgr = new ServerManager())
            {
                ApplicationPool pool = mgr.ApplicationPools.Add(name);
                if (!String.IsNullOrEmpty(username))
                {
                    pool.ProcessModel.UserName = username;
                    pool.ProcessModel.Password = password;
                }
                if (pool.ProcessModel.IdentityType != identityType)
                {
                    pool.ProcessModel.IdentityType = identityType;
                }
                if (appPoolPipelineMode != pool.ManagedPipelineMode)
                {
                    pool.ManagedPipelineMode = appPoolPipelineMode;
                }
                mgr.CommitChanges();
                success = true;
                return pool;
            }
        }

        public static ApplicationPool GetAppPool(string name)
        {
            using (ServerManager mgr = new ServerManager())
            {
                foreach (var pool in mgr.ApplicationPools)
                {
                    if (pool.Name == name)
                    {
                        return pool;
                    }
                }
            }
            return null;
        }

        public static bool DeleteAppPool(string name)
        {
            try
            {
                using (ServerManager mgr = new ServerManager())
                {
                    ApplicationPool pool = mgr.ApplicationPools[name];
                    if (pool != null)
                    {
                        mgr.ApplicationPools.Remove(pool);
                        mgr.CommitChanges();
                    }
                }
                return true;
            }
            catch (Exception ex)
            {

            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="siteName"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public static bool WebsiteIsExist(string siteName, string path)
        {
            using (ServerManager mgr = new ServerManager())
            {
                Site site = mgr.Sites[siteName];
                if (site != null)
                {
                    foreach (Microsoft.Web.Administration.Application app in site.Applications)
                    {
                        if (app.Path.ToUpper().Equals(path.ToUpper()))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="siteName"></param>
        /// <returns></returns>
        public static bool WebsiteIsExist(string siteName)
        {
            using (ServerManager mgr = new ServerManager())
            {
                Site site = mgr.Sites[siteName];
                if (site != null)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 新增或创建站点
        /// </summary>
        /// <param name="name">名称</param>
        /// <param name="bindingProtocol">http/https</param>
        /// <param name="bindingInformation">*:80:</param>
        /// <param name="physicalPath">物理路径</param>
        /// <param name="appPoolName">应用程序池</param>
        /// <returns></returns> 
        public static bool AddWebsite(string name, string appPool, string bindingProtocol, string bindingInformation, string physicalPath)
        {
            using (ServerManager mgr = new ServerManager())
            {
                Site site = mgr.Sites.Add(name, bindingProtocol, bindingInformation, physicalPath);
                ApplicationPool pool = GetAppPool(appPool);
                if (pool == null)
                {
                    throw new Exception("应用程序池： " + appPool + " 在IIS程序池中没找到");
                }
                //mgr.ApplicationPools[name].ManagedRuntimeVersion = "v2.0";
                mgr.ApplicationPools[appPool].ManagedRuntimeVersion = "v4.0";
                mgr.ApplicationPools[appPool].Enable32BitAppOnWin64 = true;//启用32位应用程序
                mgr.ApplicationPools[appPool].ManagedPipelineMode = ManagedPipelineMode.Integrated;
                site.Applications["/"].ApplicationPoolName = pool.Name;
                site.ServerAutoStart = true;
                mgr.CommitChanges();
            }
            return true;
        }

        /// <summary>
        /// 配置映射
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static bool ConfigureAspNet(string name, string appPool, string bindingProtocol, string bindingInformation, bool enable32, string physicalPath, string websocketUrl)
        {
            using (ServerManager mgr = new ServerManager())
            {
                Configuration webConfig = mgr.Sites[name].GetWebConfiguration();
                ConfigurationSection handlersSection = webConfig.GetSection("system.webServer/handlers");
                ConfigurationElementCollection handlersCollection = handlersSection.GetCollection();

                for (int i = 0; i < handlersCollection.Count; i++)
                {
                    ConfigurationElement removeElement = handlersCollection[i];
                    string ElementName = removeElement["name"].ToString().Trim();
                    if (ElementName == "ExtensionlessUrlHandler-Integrated-4.0")
                    {
                        handlersCollection.Remove(removeElement);
                    }
                    if (ElementName == "ExtensionlessUrlHandler-ISAPI-4.0_32bit")
                    {
                        handlersCollection.Remove(removeElement);
                    }
                    if (ElementName == "ExtensionlessUrlHandler-ISAPI-4.0_64bit")
                    {
                        handlersCollection.Remove(removeElement);
                    }
                    if (ElementName == "ExtensionlessUrlHandler-SVC-Full")
                    {
                        handlersCollection.Remove(removeElement);
                    }
                }

                try
                {
                    ConfigurationElement addElement = handlersCollection.CreateElement("add");
                    addElement["name"] = @"ExtensionlessUrlHandler-Integrated-4.0";
                    addElement["path"] = @"*.";
                    addElement["verb"] = @"GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS";
                    addElement["type"] = "System.Web.Handlers.TransferRequestHandler";
                    addElement["preCondition"] = @"integratedMode,runtimeVersionv4.0";
                    handlersCollection.AddAt(0, addElement);

                    addElement = handlersCollection.CreateElement("add");
                    addElement["name"] = @"ExtensionlessUrlHandler-ISAPI-4.0_64bit";
                    addElement["path"] = @"*.";
                    addElement["verb"] = @"GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS";
                    addElement["modules"] = @"IsapiModule";
                    addElement["scriptProcessor"] = @"%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll";
                    addElement["preCondition"] = @"classicMode,runtimeVersionv4.0,bitness64";
                    addElement["responseBufferLimit"] = 0;
                    handlersCollection.AddAt(0, addElement);

                    addElement = handlersCollection.CreateElement("add");
                    addElement["name"] = @"ExtensionlessUrlHandler-ISAPI-4.0_32bit";
                    addElement["path"] = @"*.";
                    addElement["verb"] = @"GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS";
                    addElement["modules"] = @"IsapiModule";
                    addElement["scriptProcessor"] = @"%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll";
                    addElement["preCondition"] = @"classicMode,runtimeVersionv4.0,bitness32";
                    addElement["responseBufferLimit"] = 0;
                    handlersCollection.AddAt(0, addElement);

                    addElement = handlersCollection.CreateElement("add");
                    addElement["name"] = @"ExtensionlessUrlHandler-SVC-Full";
                    addElement["path"] = @"*.svc";
                    addElement["verb"] = @"GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS";
                    addElement["modules"] = @"IsapiModule";
                    addElement["scriptProcessor"] = @"%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll";
                    addElement["resourceType"] = "Unspecified";
                    addElement["preCondition"] = @"classicMode,runtimeVersionv4.0,bitness32";
                    handlersCollection.AddAt(0, addElement);
                }
                catch (Exception ex)
                {
                    NLogger.WriteToLine(ex.Message, "错误", DateTime.Now, "配置WEB站点");
                }

                ApplicationPool ApplicationPool = mgr.ApplicationPools[appPool]; //GetAppPool(appPool);
                Configuration Configuration = mgr.Sites[name].GetWebConfiguration();
                Application Application = mgr.Sites[name].Applications["/"];

                BindingCollection Bindings = mgr.Sites[name].Bindings;
                if (Bindings != null && Bindings.Count > 0)
                {
                    Bindings[0].Protocol = bindingProtocol;
                    Bindings[0].BindingInformation = bindingInformation;
                }

                ApplicationPool.Enable32BitAppOnWin64 = enable32;

                Application.ApplicationPoolName = ApplicationPool.Name;
                Application.VirtualDirectories["/"].PhysicalPath = physicalPath;

                var section = Configuration.GetSection("system.webServer/staticContent");     //取得MimeMap所有节点(路径为:%windir%\Windows\System32\inetsrv\config\applicationHost.config)
                ConfigurationElement mimesElement = section.GetCollection();
                ConfigurationElementCollection mimesCollection = mimesElement.GetCollection();

                List<string> dlist = new List<string>();
                for (int i = 0; i < mimesCollection.Count; i++)
                {
                    dlist.Add(mimesCollection[i].Attributes["fileExtension"].Value + "");
                }

                if (!dlist.Contains(".json"))
                {
                    ConfigurationElement mimeElement = mimesCollection.CreateElement(); //新建MimeMap节点
                    mimeElement.Attributes["fileExtension"].Value = ".json"; //.xaml application/xaml+xml
                    mimeElement.Attributes["mimeType"].Value = "application/json";
                    mimesCollection.Add(mimeElement);
                }

                if (!dlist.Contains(".xaml"))
                {
                    ConfigurationElement mimeElement = mimesCollection.CreateElement(); //新建MimeMap节点
                    mimeElement.Attributes["fileExtension"].Value = ".json"; //.xaml application/xaml+xml
                    mimeElement.Attributes["mimeType"].Value = "application/xaml+xml";
                    mimesCollection.Add(mimeElement);
                }

                section = Configuration.GetSection("appSettings");
                for (int i = 0; i < section.GetCollection().Count; i++)
                {
                    var sectionNode = section.GetCollection()[i];
                    if (sectionNode.GetAttributeValue("key").Equals("webSocketServer"))
                    {
                        sectionNode.SetAttributeValue("value", websocketUrl);
                        break;
                    }
                }

                mgr.CommitChanges();

            }
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static WebSiteInformation GetWebsite(string name)
        {
            WebSiteInformation result = new WebSiteInformation();
            using (ServerManager mgr = new ServerManager())
            {
                Site site = mgr.Sites[name];
                if (site != null)
                {
                    result.Name = site.Name;
                    Application Application = site.Applications["/"];
                    VirtualDirectory VirtualDirectory = Application.VirtualDirectories["/"];
                    result.Path = Application.Path;
                    result.PhysicalPath = VirtualDirectory.PhysicalPath;
                    result.UserName = VirtualDirectory.UserName;
                    result.Password = VirtualDirectory.Password;
                    result.AppPoolName = Application.ApplicationPoolName;
                    result.BindingInformation = site.Bindings[0].BindingInformation;
                    result.BindingProtocol = site.Bindings[0].Protocol;
                    result.RuntimeVersion = mgr.ApplicationPools[Application.ApplicationPoolName].ManagedRuntimeVersion;
                    result.ManagedPipelineMode = mgr.ApplicationPools[Application.ApplicationPoolName].ManagedPipelineMode;

                    string WebsocketUrl = string.Empty;
                    Configuration configure = site.GetWebConfiguration();
                    ConfigurationSection section = configure.GetSection("appSettings");
                    if (section != null)
                    {
                        for (int i = 0; i < section.GetCollection().Count; i++)
                        {
                            var sectionNode = section.GetCollection()[i];
                            if (sectionNode.GetAttributeValue("key").Equals("webSocketServer"))
                            {
                                WebsocketUrl = sectionNode.GetAttributeValue("value") + "";
                                break;
                            }
                        }
                    }
                    result.WebsocketUrl = WebsocketUrl.Trim();
                }
            }
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static bool DeleteWebsite(string name)
        {
            using (ServerManager mgr = new ServerManager())
            {
                Site site = mgr.Sites[name];
                if (site != null)
                {
                    mgr.Sites.Remove(site);
                    mgr.CommitChanges();
                }
            }
            return true;
        }

    }

    public class WebSiteInformation
    {
        /// <summary>
        /// 站点名称
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 路径
        /// </summary>
        public string Path { get; set; }
        /// <summary>
        /// 物理路径
        /// </summary>
        public string PhysicalPath { get; set; }
        /// <summary>
        /// 协义头
        /// </summary>
        public string BindingProtocol { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string BindingInformation { get; set; }
        /// <summary>
        /// 应用程序池名称
        /// </summary>
        public string AppPoolName { get; set; }
        /// <summary>
        /// 用户名
        /// </summary>
        public string UserName { get; set; }
        /// <summary>
        /// 密码
        /// </summary>
        public string Password { get; set; }
        /// <summary>
        /// .NET 运行时版本
        /// </summary>
        public string RuntimeVersion { get; set; }
        /// <summary>
        /// Websocket 服务地址
        /// </summary>
        public string WebsocketUrl { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public ManagedPipelineMode ManagedPipelineMode { get; set; }
    }
}
